/*
 * grade.cpp
 *
 *  Created on: 2015��3��23��
 *      Author: Administrator
 */

#include "grading.h"

#include <cctype>
#include <list>

using namespace std;

vector<string> split(const string& s) {
	vector<string> ret;
	string::size_type i = 0;

	while (i != s.size()) {
		while (i != s.size() && isspace(s[i]))
			i++;
		string::size_type j = i;
		while (j != s.size() && !isspace(s[j]))
			j++;
		if (i != j) {
			ret.push_back(s.substr(i, j - i));
			i = j;
		}
	}
	return ret;
}

string::size_type width(const vector<string>& v) {
	string::size_type maxlen = 0;
	vector<string>::const_iterator iter = v.begin();
	while(iter != v.end()){
		maxlen = max(maxlen, iter->size());
	}
	return maxlen;
}

vector<string> frame(const vector<string>& v){
	vector<string> ret;
	string::size_type maxlen = width(v);
	string border(maxlen+4, '*');

	ret.push_back(border);
	for (vector<string>::const_iterator iter = v.begin(); iter != v.end(); iter++) {
		ret.push_back("* " + *iter + string(maxlen - iter->size(), ' ') + " *");
	}
	ret.push_back(border);
	return ret;
}

vector<string> vcat(const vector<string>& top, const vector<string>& bottom){
	vector<string> ret = top;
	ret.insert(ret.end(), bottom.begin(), bottom.end());
	return ret;
}

vector<string> hcat(const vector<string>& left, const vector<string>& right){
	vector<string> ret;
	string::size_type width1 = width(left) + 1;
	vector<string>::size_type i = 0, j = 0;

	while(i!=left.size() || j!=right.size()){
		string s;
		if(i != left.size())
			s = left[i++];
		s += string(width1 - s.size(), ' ');
		if(j != s.size())
			s += right[j++];
		ret.push_back(s);
	}
	return ret;
}


// predicate to determine whether a student failed
bool fgrade(const Student_info& s) {
	return grade(s) < 60;
}

// second try: correct but potentially slow
list<Student_info> extract_fails(list<Student_info>& students) {
	list<Student_info> fail;
	list<Student_info>::iterator iter = students.begin();

	// invariant:elements [0, i) of students represent passing grades
	while (iter != students.end()) {
		if (fgrade(*iter)) {
			fail.push_back(*iter);
			students.erase(iter);
		} else
			++iter;
	}
	return fail;
}

int main() {
	vector<Student_info> students;
	Student_info record;
	string::size_type maxlen = 0;       // the length of the longest name

	// read and store all the students data.
	// Invariant:  students contains all the student records read so far
	//   maxlen contains the length of the longest name in students
	while (read(cin, record)) {
		// find length of longest name
		maxlen = max(maxlen, record.name.size());
		students.push_back(record);
	}

	// alphabetize the student records
	sort(students.begin(), students.end(), compare);

	// write the names and grades
	for (vector<Student_info>::size_type i = 0; i != students.size(); ++i) {

		// write the name, padded on the right to maxlen + 1 characters
		cout << students[i].name
				<< string(maxlen + 1 - students[i].name.size(), ' ');

		// compute and write the grade
		try {
			double final_grade = grade(students[i]);
			streamsize prec = cout.precision();
			cout << setprecision(3) << final_grade << setprecision(prec);
		} catch (domain_error e) {
			cout << e.what();
		}
		cout << endl;
	}
	return 0;
}

